Skip to content

Apply the libcalico-go write defaults in the CRD schemas - #13872

Open
caseydavenport wants to merge 7 commits into
projectcalico:masterfrom
caseydavenport:casey-crd-defaulting-parity
Open

caseydavenport wants to merge 7 commits into
projectcalico:masterfrom
caseydavenport:casey-crd-defaulting-parity

Conversation

@caseydavenport

@caseydavenport caseydavenport commented Sep 10, 2026

Copy link
Copy Markdown
Member

Description

Resources written through the native projectcalico.org/v3 CRDs were stored without the field defaults the aggregated API server used to persist, so a raw kubectl or GitOps reader saw empty values where the docs promise otherwise. Calico's own components were unaffected, since libcalico-go applies the same defaults on read.

  • IP pool ipipMode, vxlanMode and allowedUses now take CRD schema defaults, matching what libcalico-go writes.
  • The same for FelixConfiguration floatingIPs, bpfConnectTimeLoadBalancing and bpfHostNetworkedNATWithoutCTLB. These sit at the lowest-precedence config source, below environment variables, and the values match Felix's own built-in defaults.
  • KubeControllersConfiguration prometheusMetricsPort defaults to 9094 rather than reading as 0, which meant metrics disabled.
  • blockSize takes a MutatingAdmissionPolicy rather than a schema default, since IPv4 wants 26 and IPv6 wants 122. It defaults on update as well as create, because the immutability rule is a CEL transition rule that cannot fire on an absent field, so a write omitting blockSize could otherwise clear it.

The defaults land on the v1 crd.projectcalico.org CRDs as well, since both sets generate from the same Go types. Aggregated-mode writes already persisted these values, and the v1/v3 consistency check still passes.

Found during the v3.33 test cycle, Zephyr OS-R233.

Related: CORE-13651

Release note:

Fixes IP pool, Felix and kube-controllers configuration fields being stored without their documented default values when written through the projectcalico.org/v3 CRDs.

AI assistance: Claude Code

By opening this PR you take responsibility for every line in it, and you agree to explain the change yourself during review rather than routing review comments back through an agent. See AI_POLICY.md.

Copilot AI lite review requested due to automatic review settings September 10, 2026 20:52
@caseydavenport
caseydavenport requested a review from a team as a code owner September 10, 2026 20:52
@caseydavenport caseydavenport added release-note-required Change has user-facing impact (no matter how small) docs-not-required Docs not required for this change cherry-pick-candidate labels Sep 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Native CRD writes bypass libcalico-go, so the schemas carry the IP pool, Felix
and kube-controllers defaults it applies on write. blockSize takes a
MutatingAdmissionPolicy instead, since the value depends on whether the CIDR is
v4 or v6.

Found during the v3.33 test cycle, Zephyr OS-R233.

CORE-13651
The immutability rule is a CEL transition rule, so it does not fire when the
field is absent from the incoming object. Defaulting on update means a write
that omits blockSize gets the stored value back rather than zero.

CORE-13651
A static schema default also lands on pools that set a namespaceSelector, which
the schema then rejects for combining a namespaceSelector with Tunnel. The
policy defaults those pools to Workload alone.

CORE-13651
Kubernetes 1.32 has no MutatingAdmissionPolicy, so the schema-defaults test
cannot expect a value the policy supplies.

CORE-13651
The test compares the stored object against the one it wrote, so every field
the schema defaults has to be in the input.

CORE-13651
@caseydavenport
caseydavenport force-pushed the casey-crd-defaulting-parity branch from deadf4f to 38b9513 Compare September 14, 2026 18:54
Both specs compare a stored object against the one they wrote, so the fields the
CRD now defaults have to be in the expectation.

CORE-13651
etcdv3 has no CRD schema, so a raw backend write stores the empty modes.

CORE-13651
@caseydavenport
caseydavenport requested a review from a team as a code owner September 16, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-pick-candidate docs-not-required Docs not required for this change release-note-required Change has user-facing impact (no matter how small)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants